package org.javahispano.javacup.tacticas_aceptadas.josephdke;

import java.awt.Color;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.EstiloUniforme;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;
import org.javahispano.javacup.modelo.Tactica;
import org.javahispano.javacup.modelo.TacticaDetalle;

public class TacticaDinamoGANA implements Tactica {

    Posicion alineacion1[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-12.125874125874127,-43.47285067873303),
        new Posicion(-6.6573426573426575,-27.556561085972852),
        new Posicion(13.552447552447552,-43.47285067873303),
        new Posicion(8.321678321678322,-33.73303167420815),
        new Posicion(-1.188811188811189,-13.540723981900454),
        new Posicion(-18.545454545454543,-0.47511312217194573),
        new Posicion(14.503496503496503,-2.8506787330316743),
        new Posicion(-15.216783216783217,28.031674208144796),
        new Posicion(0.4755244755244755,14.490950226244346),
        new Posicion(9.748251748251748,37.53393665158371)
    };

    Posicion alineacion2[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-31.082089552238806),
        new Posicion(11.16030534351145,-31.6044776119403),
        new Posicion(27.251908396946565,-27.94776119402985),
        new Posicion(-29.84732824427481,-26.902985074626866),
        new Posicion(6.895104895104895,-9.739819004524888),
        new Posicion(-8.797202797202797,-8.552036199095022),
        new Posicion(0.23776223776223776,-24.705882352941178),
        new Posicion(15.216783216783217,-1.6628959276018098),
        new Posicion(-1.188811188811189,-13.778280542986426),
        new Posicion(-15.216783216783217,-1.900452488687783)
    };

    Posicion alineacion3[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-31.082089552238806),
        new Posicion(11.16030534351145,-31.6044776119403),
        new Posicion(26.732824427480914,-20.111940298507463),
        new Posicion(-29.32824427480916,-21.67910447761194),
        new Posicion(-0.951048951048951,-15.678733031674208),
        new Posicion(-18.946564885496183,-0.26119402985074625),
        new Posicion(18.946564885496183,-0.26119402985074625),
        new Posicion(-32.0979020979021,-0.9502262443438915),
        new Posicion(-0.7132867132867133,-1.1877828054298643),
        new Posicion(32.0979020979021,-0.9502262443438915)
    };

    Posicion alineacion4[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-31.082089552238806),
        new Posicion(11.16030534351145,-31.6044776119403),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(11.16030534351145,-1.3059701492537314),
        new Posicion(-10.641221374045802,-0.7835820895522387),
        new Posicion(-27.251908396946565,31.6044776119403),
        new Posicion(-10.641221374045802,30.559701492537314),
        new Posicion(9.603053435114505,28.992537313432837),
        new Posicion(25.69465648854962,28.992537313432837)
    };

    Posicion alineacion5[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(14.793893129770993,-18.544776119402986),
        new Posicion(-17.389312977099234,-19.58955223880597),
        new Posicion(-23.618320610687025,-0.7835820895522387),
        new Posicion(5.969465648854961,-5.485074626865671),
        new Posicion(0.2595419847328244,-0.26119402985074625),
        new Posicion(22.580152671755727,-1.3059701492537314)
    };

    Posicion alineacion6[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(14.793893129770993,-18.544776119402986),
        new Posicion(-17.389312977099234,-19.58955223880597),
        new Posicion(-23.618320610687025,-0.7835820895522387),
        new Posicion(6.4885496183206115,-6.529850746268657),
        new Posicion(-6.4885496183206115,-6.529850746268657),
        new Posicion(22.580152671755727,-1.3059701492537314)
    };

    class TacticaDetalleImpl implements TacticaDetalle {

        public String getNombre() {
            return "DinamoGANA";
        }

        public String getPais() {
            return "Colombia";
        }

        public String getEntrenador() {
            return "JosephDkE";
        }

        public Color getColorCamiseta() {
            return new Color(255, 255, 255);
        }

        public Color getColorPantalon() {
            return new Color(0, 0, 0);
        }

        public Color getColorFranja() {
            return new Color(0, 153, 102);
        }

        public Color getColorCalcetas() {
            return new Color(255, 255, 255);
        }

        public Color getColorPortero() {
            return new Color(153, 0, 51        );
        }

        public EstiloUniforme getEstilo() {
            return EstiloUniforme.LINEAS_VERTICALES;
        }

        public Color getColorCamiseta2() {
            return new Color(0, 0, 0);
        }

        public Color getColorPantalon2() {
            return new Color(45, 89, 22);
        }

        public Color getColorFranja2() {
            return new Color(255, 255, 255);
        }

        public Color getColorCalcetas2() {
            return new Color(0, 0, 0);
        }

        public Color getColorPortero2() {
            return new Color(153, 0, 51        );
        }

        public EstiloUniforme getEstilo2() {
            return EstiloUniforme.FRANJA_HORIZONTAL;
        }

        class JugadorImpl implements JugadorDetalle {

            String nombre;
            int numero;
            Color piel, pelo;
            double velocidad, remate, presicion;
            boolean portero;
            Posicion posicion;

            public JugadorImpl(String nombre, int numero, Color piel, Color pelo,
                    double velocidad, double remate, double presicion, boolean portero) {
                this.nombre=nombre;
                this.numero=numero;
                this.piel=piel;
                this.pelo=pelo;
                this.velocidad=velocidad;
                this.remate=remate;
                this.presicion=presicion;
                this.portero=portero;
            }

            public String getNombre() {
                return nombre;
            }

            public Color getColorPiel() {
                return piel;
            }

            public Color getColorPelo() {
                return pelo;
            }

            public int getNumero() {
                return numero;
            }

            public boolean esPortero() {
                return portero;
            }

            public double getVelocidad() {
                return velocidad;
            }

            public double getRemate() {
                return remate;
            }

            public double getPresicion() {
                return presicion;
            }

        }

        public JugadorDetalle[] getJugadores() {
            return new JugadorDetalle[]{
                new JugadorImpl("Juan Camilo", 1, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, true),
                new JugadorImpl("Stiven", 2, new Color(102,102,0), new Color(50,0,0),1.0d,1.0d,0.0d, false),
                new JugadorImpl("Arbey", 3, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.0d, false),
                new JugadorImpl("Victor", 4, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.0d, false),
                new JugadorImpl("David", 5, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.0d, false),
                new JugadorImpl("Johan", 6, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.0d, false),
                new JugadorImpl("Sergio", 7, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.75d, false),
                new JugadorImpl("Jessid", 8, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.75d, false),
                new JugadorImpl("Jose", 9, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                new JugadorImpl("Lisandro", 10, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                new JugadorImpl("Alex", 11, new Color(153,153,0), new Color(50,0,0),1.0d,1.0d,1.0d, false)
            };
        }
    }

    TacticaDetalle detalle=new TacticaDetalleImpl();
    public TacticaDetalle getDetalle() {
        return detalle;
    }

    public Posicion[] getPosicionSaca(SituacionPartido sp) {
    	return alineacion3;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
    	return alineacion2;
    }

    //***********************************************************************************************************************
    //*******
    //******* SECCION PROPIA
	//*******
	//***********************************************************************************************************************

    class ComandoGANA {
    	public int comando = 0;
    	// Seg�n el comando
    	public Object parametroComando1 = null;
    	public Object parametroComando2 = null;
    	public Object parametroComando3 = null;
    	public Object parametroComando4 = null;
    	// Si el comando aplica solo para cuando ocurra otro comando
    	public int comandoActivacion = -1;
    	// Guarda el "comando" resultante
    	public Comando comandoJuego = null;
    	// Iteraci�n en la que se cre� el comando
    	public int iteracion = 0;
    	public boolean comandoTerminado = false;

    	public ComandoGANA( int comando, Object... parametros ){
    		this.comando = comando;
    		this.parametroComando1 = ( parametros.length > 0 ) ? parametros[0] : null;
    		this.parametroComando2 = ( parametros.length > 1 ) ? parametros[1] : null;
    		this.parametroComando3 = ( parametros.length > 2 ) ? parametros[2] : null;
    		this.parametroComando4 = ( parametros.length > 3 ) ? parametros[3] : null;
    		this.comandoActivacion = -1;
    		this.iteracion = TacticaDinamoGANA.this.iteracion;
    		this.comandoTerminado = false;
    	}

    	public ComandoGANA( int comando, int comandoActivacion, Object... parametros ){
    		this( comando, parametros );
    		this.comandoActivacion = comandoActivacion;
    	}
    }

    class JugadorGANA {
    	public int indice = 0;
    	public Posicion posicionActual = null;
    	public int iteracionPosicionActual = 0;
    	public Posicion posicionAnterior = null;
    	public int iteracionPosicionAnterior = 0;

    	public ComandoGANA comando = null;
    	public ComandoGANA comandoAnterior = null;
    	public ArrayList comandosSiguientes = new ArrayList();

    	public JugadorGANA( int indice ){
    		this.indice = indice;
    	}

    	public void setComando( ComandoGANA comando ){
    		if( comando.comando == MOVERSE_EN_POSICION ){
    			if( this.comando == null || this.comando.comando != MOVERSE_EN_POSICION ){
    				this.comando = comando;
    				this.comando.iteracion = TacticaDinamoGANA.this.iteracion;
    			}
    		}
    		else {
    			this.comando = comando;
    			this.comando.iteracion = TacticaDinamoGANA.this.iteracion;
    		}
    	}

    	public void addComandoSiguiente( ComandoGANA comando ){
    		int i, index = -1;
    		for( i=0; i<this.comandosSiguientes.size() && index == -1; i++ ){
    			ComandoGANA com = (ComandoGANA)this.comandosSiguientes.get( i );
    			if( com.comandoActivacion == comando.comandoActivacion )
    				index = i;
    		}
    		if( index == -1 )
    			this.comandosSiguientes.add( comando );
    		else
    			this.comandosSiguientes.set( index, comando );
    	}

    }

    private JugadorGANA[] jugadores = null;
    private int iteracion = 0;
    private int iteracionAnterior = -1;
    private int offsetPase = 3;

    Random rand = new Random();
    LinkedList<Comando> comandos = new LinkedList<Comando>();

    private double lastBallPositionX = 0;
    private double lastBallPositionY = 0;
    private double lastBallPositionXPiso = 0;
    private double lastBallPositionYPiso = 0;
    private double lastTiroBallPositionXPiso = -1;
    private double lastTiroBallPositionYPiso = -1;

    public final int SEGUIR_BALON = 1;
    public final int SEGUIR_JUGADOR = 2;
    public final int INTERCEPTAR_PASE = 3;
    public final int ACHICAR = 4;
    public final int MOVER_A_POSICION = 5;
    public final int TAPAR = 6;
    public final int GOLPEAR_BALON = 7;
    public final int MOVERSE_EN_POSICION = 8;
    public final int RECIBIR_PASE = 9;
    public final int BUSCAR_PASE = 10;
    public final int BUSCAR_PARED = 11;

    private int indiceEnLista( int indice, int[] lista ){
    	int i;
    	for( i=0; i<lista.length; i++ ){
    		if( lista[i] == indice ){
    			return i;
    		}
    	}
    	return -1;
    }

    private boolean cambioComando( JugadorGANA jugador, Posicion nuevaPosicion ){
		boolean apply = true;
    	if( jugador.comandoAnterior.comando == jugador.comando.comando ){
			Posicion posAnterior = (Posicion)jugador.comandoAnterior.parametroComando1;
			if( posAnterior != null ){
				BigDecimal bd = new BigDecimal(posAnterior.getX());
				bd = bd.setScale( 11, BigDecimal.ROUND_HALF_UP );
				double x1 = bd.doubleValue();
				bd = new BigDecimal( nuevaPosicion.getX() );
				bd = bd.setScale( 11, BigDecimal.ROUND_HALF_UP );
				double x2 = bd.doubleValue();
				if( x1 == x2 )
					apply = false;
			}
		}
		return apply;
    }

    private Posicion obtenerPosicionRechazo( Posicion jugadorPosicion, SituacionPartido sp, int[] masCercanosRivales, int tipoRechazo ){
		Posicion rivalMasCecano = sp.rivales()[masCercanosRivales[0]];
		double x = rivalMasCecano.getX();
		if( tipoRechazo == 3 )
			x = jugadorPosicion.getX();
		if( x < 0 )
			x = Constantes.ANCHO_CAMPO_JUEGO / 2;
		else
			x = -Constantes.ANCHO_CAMPO_JUEGO / 2;
		double py = -Constantes.LARGO_CAMPO_JUEGO/4;
		if( tipoRechazo == 2 )
			py = jugadorPosicion.getY() + 10;
		if( tipoRechazo == 3 )
			py = -10;
		Posicion posicionRechazo = new Posicion( x, py );
		return posicionRechazo;
    }

    private boolean evaluarDecision( int indiceJugador, JugadorGANA jugador, Posicion jugadorPosicion, SituacionPartido sp, double movimientoBalon, boolean puedeRematar, double distanciaJugadorBalon, int[] rematanRivales, int[] rematanAmigos, int[] masCercanosRivalesBalon, int[] masCercanosAmigosBalon, int[] masCercanosRivales, int[] masCercanosAmigos, int rivalMasCercanoBalon, int amigoMasCercanoBalon, double distanciaRivalMasCercanoBalon, double distanciaAmigoMasCercanoBalon, int cantidadSiguenBalon, Posicion posicionTiroRival ){
    	if( jugador.comandosSiguientes.size()>0 ){
    		ComandoGANA com = (ComandoGANA)jugador.comandosSiguientes.get( 0 );
    		if( com.comandoActivacion == -1 ){
	    		jugador.comando = com;
	    		jugador.comandosSiguientes.remove(0);
	    		return false;
    		}
    	}
    	boolean resultado = false;
    	if( jugador.comando != null && iteracion != iteracionAnterior &&
    		( jugador.comando.iteracion == iteracion && jugador.comando.comando != MOVERSE_EN_POSICION ) ){
    		return false;
    	}
    	switch( indiceJugador ){
    		case 0:
    			resultado = evaluarDecisionArquero( indiceJugador, jugador, jugadorPosicion, sp, movimientoBalon, puedeRematar, distanciaJugadorBalon, rematanRivales, rematanAmigos, masCercanosRivalesBalon, masCercanosAmigosBalon, masCercanosRivales, masCercanosAmigos, rivalMasCercanoBalon, amigoMasCercanoBalon, distanciaRivalMasCercanoBalon, distanciaAmigoMasCercanoBalon, cantidadSiguenBalon, posicionTiroRival );
    			break;
    		default:
    			resultado = evaluarDecisionJugador( indiceJugador, jugador, jugadorPosicion, sp, movimientoBalon, puedeRematar, distanciaJugadorBalon, rematanRivales, rematanAmigos, masCercanosRivalesBalon, masCercanosAmigosBalon, masCercanosRivales, masCercanosAmigos, rivalMasCercanoBalon, amigoMasCercanoBalon, distanciaRivalMasCercanoBalon, distanciaAmigoMasCercanoBalon, cantidadSiguenBalon, posicionTiroRival );
    			break;
    	}
    	if( jugador.comandosSiguientes.size()>0 ){
    		ComandoGANA com = (ComandoGANA)jugador.comandosSiguientes.get( 0 );
    		if( com.iteracion != iteracion && ( com.comandoActivacion == 0 || com.comandoActivacion == jugador.comando.comando ) ){
	    		jugador.comando = com;
	    		jugador.comandosSiguientes.remove(0);
	    		resultado = false;
    		}
    	}
    	return resultado;
    }

    public List<Comando> ejecutar( SituacionPartido sp ) {
    	int i;
    	// 1. Inicia la lista de jugadores
    	if( jugadores == null ){
    		jugadores = new JugadorGANA[11];
        	for( i=0; i<11; i++ )
        		jugadores[i] = new JugadorGANA( i );
    	}

    	// Actualiza la iteraci�na actual
    	iteracionAnterior = iteracion;
    	iteracion = sp.iteracion();

    	// Actualiza la posici�n de los jugadores con la posici�n actual
    	for( i=0; i<11; i++ ){
    		Posicion pos = sp.misJugadores()[i];
    		if( jugadores[i].posicionAnterior == null || jugadores[i].posicionAnterior.getX() != pos.getX() || jugadores[i].posicionAnterior.getY() != pos.getY() ){
    			jugadores[i].posicionAnterior = jugadores[i].posicionActual;
    			jugadores[i].iteracionPosicionAnterior = jugadores[i].iteracionPosicionActual;
    			jugadores[i].posicionActual = pos;
    			jugadores[i].iteracionPosicionActual = iteracion;
    		}
    	}

    	// Datos importantes para decisiones
    	int rematanRivales[] = sp.puedenRematarRival();
    	int rematanAmigos[] = sp.puedenRematar();
    	int[] masCercanosRivalesBalon = sp.balon().indicesMasCercanos( sp.rivales() );
    	int[] masCercanosAmigosBalon = sp.balon().indicesMasCercanos( sp.misJugadores() );
    	int rivalMasCercanoBalon = masCercanosRivalesBalon[0];
    	int amigoMasCercanoBalon = masCercanosAmigosBalon[0];
    	double distanciaRivalMasCercanoBalon = sp.rivales()[rivalMasCercanoBalon].distancia( sp.balon() );
    	double distanciaAmigoMasCercanoBalon = sp.misJugadores()[amigoMasCercanoBalon].distancia( sp.balon() );
    	double movimientoBalon = sp.balon().getY()-lastBallPositionY;

		// Valida si nos est�n atacando
    	Posicion posicionTiroRival = null;
		if( movimientoBalon < 0 ) {
			if( sp.alturaBalon() == 0 ){
		    	lastBallPositionXPiso = sp.balon().getX();
		        lastBallPositionYPiso = sp.balon().getY();
			}
			else {
				if( lastBallPositionXPiso != lastTiroBallPositionXPiso || lastBallPositionYPiso != lastTiroBallPositionYPiso ){
    				// Trata de interceptar el bal�n en lugar de seguirlo "ciegamente"
					double balonDz = sp.alturaBalon();
					double balonDx = sp.balon().getX() - lastBallPositionXPiso;
		    		double balonDy = sp.balon().getY() - lastBallPositionYPiso;

		    		double alturaBalon = sp.alturaBalon();
	    			alturaBalon = redondeaMultiplo(alturaBalon + balonDz, Constantes.G);
	    			balonDz = redondeaMultiplo(balonDz - Constantes.G, Constantes.G);

		    		double totalX = balonDx;
		            double totalY = balonDy;
		    		while( alturaBalon > 1.2 ){
		    			alturaBalon = redondeaMultiplo(alturaBalon + balonDz, Constantes.G);
		    			if( alturaBalon > 1.2 ){
		    				balonDz = redondeaMultiplo(balonDz - Constantes.G, Constantes.G);
		    				balonDx = balonDx * Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE;
		    				balonDy = balonDy * Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE;
		    				totalX += balonDx;
		    				totalY += balonDy;
		    			}
	    			}
		    		posicionTiroRival = new Posicion( lastBallPositionXPiso+totalX, lastBallPositionYPiso+totalY );
		    		lastTiroBallPositionXPiso = lastBallPositionXPiso;
		    		lastTiroBallPositionYPiso = lastBallPositionYPiso;
				}
			}
		}

    	// Valida si los comandos previamente "programados" ya terminaron ( La condici�n var�a seg�n el comando )
    	for( i=0; i<11; i++ ){
    		Posicion jugador = sp.misJugadores()[i];
    		procesarComandoActual( i, jugadores[i], jugador, sp, movimientoBalon, jugadores[i].comando, masCercanosAmigosBalon, rematanRivales );
    	}

    	// Toma las "decisiones" por cada jugador
    	int cantidadSiguenBalon = 0;
    	for( i=0; i<11; i++ ){
    		Posicion jugador = sp.misJugadores()[i];
    		int[] masCercanosRivales = jugador.indicesMasCercanos( sp.rivales() );
    		int[] masCercanosAmigos = jugador.indicesMasCercanos( sp.misJugadores() );
    		boolean puedeRematar = ( indiceEnLista( i, rematanAmigos ) != -1 );
    		double distanciaJugadorBalon = sp.balon().distancia( jugador );
    		boolean sigueElBalon = evaluarDecision( i, jugadores[i], jugador, sp, movimientoBalon, puedeRematar, distanciaJugadorBalon, rematanRivales, rematanAmigos, masCercanosRivalesBalon, masCercanosAmigosBalon, masCercanosRivales, masCercanosAmigos, rivalMasCercanoBalon, amigoMasCercanoBalon, distanciaRivalMasCercanoBalon, distanciaAmigoMasCercanoBalon, cantidadSiguenBalon, posicionTiroRival );
    		if( sigueElBalon )
    			cantidadSiguenBalon++;
    	}

    	// Actualiza los comandos
    	comandos.clear();
    	for( i=0; i<11; i++ ){
    		Posicion jugador = sp.misJugadores()[i];
    		Comando comando = ejecutarComando( i, sp, jugador, movimientoBalon );
    		comandos.add( comando );
    	}

        // Actualiza las variables globales
    	lastBallPositionX = sp.balon().getX();
        lastBallPositionY = sp.balon().getY();

        return comandos;
    }

    //***********************************************************************************************************************
    //*******
    //******* SECCION DINAMICA
	//*******
	//***********************************************************************************************************************

    private void procesarComandoActual( int indiceJugador, JugadorGANA jugador, Posicion jugadorPosicion, SituacionPartido sp, double movimientoBalon, ComandoGANA comando, int[] masCercanosAmigosBalon, int rematanRivales[] ){
    	if( comando == null )
    		return;

    	// Si el rival intercept� el bal�n o el jugador lleva m�s de 10 iteraciones en el mismo punto termina su comando actual
    	// Si el bal�n va hacia nuestro lado, termina el comando tambi�m
    	if( !comando.comandoTerminado && ( rematanRivales.length > 0 || iteracion - jugador.iteracionPosicionActual > 10 || ( comando.comando != INTERCEPTAR_PASE && movimientoBalon < 0 ) ) ){
    		comando.comandoTerminado = true;
    	}

    	switch( comando.comando ){
    		case RECIBIR_PASE:
	    		// Si el usuario se program� para recibir el pase, se debe ajustar, ya que el pasador tiene un porcentaje de "error" en el pase.
    			double dz = sp.alturaBalon();
	    		if( dz > 0 ){
	    			// Una vez conocida la altura, replantea la "caida" del pase con el angulo despu�s de generado el error
	    			Posicion posicion = castPosicion( jugador.comando.parametroComando4, null );
	    			double fuerza = castDouble( jugador.comando.parametroComando2, 1.0 );
	    			double anguloVert = castDouble( jugador.comando.parametroComando3, 30.0 );

	    			double angConvert = Math.PI / 180d;
	    			double angVer = Math.min(anguloVert, Constantes.ANGULO_VERTICAL_MAX);
	                angVer = Math.max(angVer, 0);
	                angVer = angVer * angConvert;

	    			JugadorDetalle ju = sp.detalleMisJugadores()[indiceJugador];
	    			double vel = fuerza * Constantes.getVelocidadRemate(ju.getRemate());//calcula la velocidad del remate

	    			vel = vel * Math.cos(angVer);
	    			double balonDz = redondeaMultiplo(vel * Math.sin(angVer), Constantes.G);
		    		double balonDx = sp.balon().getX() - posicion.getX();
		    		double balonDy = sp.balon().getY() - posicion.getY();

		    		double alturaBalon = sp.alturaBalon();
	    			alturaBalon = redondeaMultiplo(alturaBalon + balonDz, Constantes.G);
	    			balonDz = redondeaMultiplo(balonDz - Constantes.G, Constantes.G);

		    		double totalX = balonDx;
		            double totalY = balonDy;
		    		while( alturaBalon > 0 ){
		    			alturaBalon = redondeaMultiplo(alturaBalon + balonDz, Constantes.G);
		    			if( alturaBalon > 0 ){
		    				balonDz = redondeaMultiplo(balonDz - Constantes.G, Constantes.G);
		    				balonDx = balonDx * Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE;
		    				balonDy = balonDy * Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE;
		    				totalX += balonDx;
		    				totalY += balonDy;
		    			}
	    			}
		    		Posicion posicionPase = new Posicion( posicion.getX()+totalX, posicion.getY()+totalY );
		    		jugadores[indiceJugador].setComando( new ComandoGANA( BUSCAR_PASE, posicionPase ) );
	    		}
	    		// Si no no tiene break p�rque debe hacer lo mismo que buscar_pase
    		case BUSCAR_PARED:
				break;
    		case BUSCAR_PASE:
    			// Cuando el bal�n cae al piso, cancela el comado para que siga detr�s del bal�n
    			if( sp.alturaBalon() == 0 )
    				comando.comandoTerminado = true;
    			break;
    		case GOLPEAR_BALON:
    			comando.comandoTerminado = true;
    			break;
    		case MOVERSE_EN_POSICION:
    			//comando.comandoTerminado = true;
    			break;
    		case MOVER_A_POSICION:
    			break;
    		case SEGUIR_BALON:
    			if( masCercanosAmigosBalon[0] != indiceJugador && jugadorPosicion.distancia( alineacion1[ indiceJugador ] ) > 25 ){
    				jugadores[indiceJugador].setComando( new ComandoGANA( MOVERSE_EN_POSICION ) );
    			}
    			break;
    	}
    }

    private Comando ejecutarComando( int indiceJugador, SituacionPartido sp, Posicion jugadorPosicion, double movimientoBalon ){
    	Comando comandoJuego = null;
    	JugadorGANA jugador = jugadores[indiceJugador];
    	if( jugador.comando == null )
    		jugador.setComando( new ComandoGANA( MOVER_A_POSICION ) );
    	int comando = jugador.comando.comando;
    	double balonX = sp.balon().getX(), x = 0, m = 0, y;
    	double posYPorteria = ( -Constantes.LARGO_CAMPO_JUEGO / 2 );
    	double posYPortero = ( -Constantes.LARGO_CAMPO_JUEGO / 2 ) + 1;
    	Posicion posicion;
    	double fuerza, anguloVert;
    	switch( comando ){
    		default:
    		case RECIBIR_PASE:
    		case BUSCAR_PASE:
    		case BUSCAR_PARED:
    		case INTERCEPTAR_PASE:
    		case MOVER_A_POSICION:
    			posicion = castPosicion( jugador.comando.parametroComando1, alineacion1[ indiceJugador ] );
    			comandoJuego = new ComandoIrA( indiceJugador, posicion );
    			getInfoComando(sp,jugador,comando,posicion);
    			break;
    		case MOVERSE_EN_POSICION:
    			posicion = castPosicion( jugador.comando.parametroComando1, alineacion1[ indiceJugador ] );
    			if( jugadorPosicion.getX() == posicion.getX() && jugadorPosicion.getY() == posicion.getY() ){
    				x = alineacion1[ indiceJugador ].getX()+(Math.random()*5.0-2.5);
    				y = alineacion1[ indiceJugador ].getY()+(Math.random()*5.0-2.5);
    				posicion = new Posicion( x, y );
    				jugador.comando.parametroComando1 = posicion;
    			}
    			comandoJuego = new ComandoIrA( indiceJugador, posicion );
    			getInfoComando(sp,jugador,comando,posicion);
    			break;
    		case SEGUIR_BALON:
    			comandoJuego = new ComandoIrA( indiceJugador, sp.balon() );
    			getInfoComando(sp,jugador,comando,sp.balon());
    			break;
    		case SEGUIR_JUGADOR:
    			int jugadorSeguido = (Integer)jugador.comando.parametroComando1;
    			comandoJuego = new ComandoIrA( indiceJugador, sp.rivales()[jugadorSeguido] );
    			getInfoComando(sp,jugador,comando,sp.rivales()[jugadorSeguido]);
    			break;
    		case TAPAR:
    			// Traza una linea entre la posici�n anterior del balon y la posicion actual
    			x = sp.balon().getX();
    			if( sp.balon().getX() - lastBallPositionX != 0 ){
					m = ( sp.balon().getY() - lastBallPositionY ) / ( sp.balon().getX() - lastBallPositionX );
					x = sp.balon().getX() - ( ( sp.balon().getY() - posYPortero ) / m );
    			}
    			if( Math.abs(x) <= ( Constantes.LARGO_ARCO / 2 )+2 ){
    				posicion = new Posicion( x, posYPortero );
    				if( cambioComando( jugador, posicion ) ){
		    			comandoJuego = new ComandoIrA( indiceJugador, posicion );
		    			getInfoComando(sp,jugador,comando,posicion);
		    			jugador.comando.parametroComando1 = posicion;
    				}
	    			break;
    			}
    		case ACHICAR:
    			// Traza una linea entre el balon y el centro de la porter�a
    			x = sp.balon().getX();
    			if( balonX != 0 ){
					m = ( sp.balon().getY() - posYPorteria ) / ( sp.balon().getX() - 0 );
					x = sp.balon().getX() - ( ( sp.balon().getY() - posYPortero ) / m );
    			}
    			posicion = new Posicion( x, posYPortero );
    			comandoJuego = new ComandoIrA( indiceJugador, posicion );
    			getInfoComando(sp,jugador,comando,posicion);
    			break;
    		case GOLPEAR_BALON:
    			posicion = castPosicion( jugador.comando.parametroComando1, null );
    			fuerza = castDouble( jugador.comando.parametroComando2, 1.0 );
    			anguloVert = castDouble( jugador.comando.parametroComando3, 30.0 );
    			comandoJuego = new ComandoGolpearBalon( indiceJugador, posicion, fuerza, anguloVert );
    			getInfoComando(sp,jugador,comando,posicion,fuerza,anguloVert);
    			break;
    	}
    	if( comandoJuego == null ){
    		comandoJuego = jugadores[indiceJugador].comandoAnterior.comandoJuego;
    	}
    	jugadores[indiceJugador].comando.comandoJuego = comandoJuego;
    	jugador.comandoAnterior = jugador.comando;
    	return comandoJuego;
    }

    private boolean evaluarDecisionArquero( int indiceJugador, JugadorGANA jugador, Posicion jugadorPosicion, SituacionPartido sp, double movimientoBalon, boolean puedeRematar, double distanciaJugadorBalon, int[] rematanRivales, int[] rematanAmigos, int[] masCercanosRivalesBalon, int[] masCercanosAmigosBalon, int[] masCercanosRivales, int[] masCercanosAmigos, int rivalMasCercanoBalon, int amigoMasCercanoBalon, double distanciaRivalMasCercanoBalon, double distanciaAmigoMasCercanoBalon, int cantidadSiguenBalon, Posicion posicionTiroRival ){
    	if( puedeRematar ){
    		Posicion posicionPase = obtenerPosicionRechazo( jugadorPosicion, sp, masCercanosRivales, 1 );
			int indiceJugadorRecibe = getJugadorMasCercano( sp, posicionPase, indiceJugador, sp.misJugadores() );
			pasarBalon( indiceJugador, indiceJugadorRecibe, sp, posicionPase );
    		jugador.addComandoSiguiente( new ComandoGANA( MOVER_A_POSICION ) );
    	}
    	else {
	    	if( sp.saco() ){
	    		jugador.setComando( new ComandoGANA( MOVER_A_POSICION ) );
	    	}
	    	else if( movimientoBalon <= 0 ){
	    		double distanciaMiArco = sp.balon().distancia( Constantes.centroArcoInf );
	    		if( distanciaMiArco > 30 ){
	    			jugador.setComando( new ComandoGANA( ACHICAR ) );
	    		}
	    		else {
	    			if( distanciaJugadorBalon < distanciaRivalMasCercanoBalon && sp.alturaBalon() < 0.5 ){
	    				jugador.setComando( new ComandoGANA( SEGUIR_BALON ) );
		    		}
		    		else if( movimientoBalon < 0 ) {
		    			jugador.setComando( new ComandoGANA( TAPAR ) );
		    			Posicion posicionRechazo = obtenerPosicionRechazo( jugadorPosicion, sp, masCercanosRivales, 1 );
		    			int jugadorRecibeIndex = getJugadorMasCercano( sp, posicionRechazo, indiceJugador, sp.misJugadores() );
		    			posicionRechazo = new Posicion( posicionRechazo.getX(), sp.misJugadores()[jugadorRecibeIndex].getY()+offsetPase );
		    			// Programa al arquero para que cuando tape el bal�n se lo pase al defensa m�s cercano a la banda contraria
		    			jugador.addComandoSiguiente( new ComandoGANA( GOLPEAR_BALON, GOLPEAR_BALON, posicionRechazo, 1.0, 45.0 ) );
		    			jugadores[jugadorRecibeIndex].setComando( new ComandoGANA( MOVER_A_POSICION, posicionRechazo ) );
		    		}
	    		}
	    	}
	    	else
	    		jugador.setComando( new ComandoGANA( MOVER_A_POSICION ) );
    	}
    	return false;
    }

    private boolean evaluarDecisionJugador( int indiceJugador, JugadorGANA jugador, Posicion jugadorPosicion, SituacionPartido sp, double movimientoBalon, boolean puedeRematar, double distanciaJugadorBalon, int[] rematanRivales, int[] rematanAmigos, int[] masCercanosRivalesBalon, int[] masCercanosAmigosBalon, int[] masCercanosRivales, int[] masCercanosAmigos, int rivalMasCercanoBalon, int amigoMasCercanoBalon, double distanciaRivalMasCercanoBalon, double distanciaAmigoMasCercanoBalon, int cantidadSiguenBalon, Posicion posicionTiroRival ){
    	if( puedeRematar ){
    		double d = jugadorPosicion.distancia( Constantes.centroArcoSup );
    		int indiceJugadorRecibe = 0;
    		if( sp.saco() ){
    			if( jugadorPosicion.getY() > 0 ){
    				indiceJugadorRecibe = buscarMejorPase( indiceJugador, jugadorPosicion, sp, masCercanosAmigos );
	    			if( indiceJugadorRecibe != -1 )
	    				pasarBalon( indiceJugador, indiceJugadorRecibe, sp, null );
	    			else {
	    	    		Posicion posicionPase = new Posicion( -Constantes.LARGO_ARCO / 2, Constantes.LARGO_CAMPO_JUEGO / 2 - 15 );
	    	    		indiceJugadorRecibe = getJugadorMasCercano( sp, posicionPase, indiceJugador, sp.misJugadores() );
	    	    		pasarBalon( indiceJugador, indiceJugadorRecibe, sp, posicionPase );
	    			}
    			}
    			else {
    				Posicion posicionPase = obtenerPosicionRechazo( jugadorPosicion, sp, masCercanosRivales, 1 );
    				indiceJugadorRecibe = getJugadorMasCercano( sp, posicionPase, indiceJugador, sp.misJugadores() );
    				pasarBalon( indiceJugador, indiceJugadorRecibe, sp, posicionPase );
    			}
    		}
    		else {
    			indiceJugadorRecibe = buscarMejorPase( indiceJugador, jugadorPosicion, sp, masCercanosAmigos );
    			int rivalesAdelante = obtenerRivalesAdelante( sp, jugadorPosicion );
    			int rivalesAdelantePase = (indiceJugadorRecibe == -1) ? -1 : obtenerRivalesAdelante( sp, sp.misJugadores()[indiceJugadorRecibe] );
    			// Si el jugador del pase est� solito
    			if( rivalesAdelantePase == 0 || rivalesAdelantePase == 1 ) {
    				pasarBalon( indiceJugador, indiceJugadorRecibe, sp, null );
    			}
    			else if ( d < 30 && Math.abs( jugadorPosicion.getX() ) < Constantes.LARGO_AREA_GRANDE / 2 ) {
			    	boolean alto = ( rivalesAdelante > 0 && d>=18 );
			    	double angulo = alto ? 45.0 : 10.0;
			    	//double fuerza = (d>25) ? 1.0 : ( d<20 ) ? 1.0 : 0.8;
			    	double fuerza = !alto ? 1.0 : (d>25) ? 1.0 : (d>20) ? 0.95 : 0.9;
			    	// Averiguamos donde est� el arquero rival
			    	Posicion arquero = sp.rivales()[ buscarPorteroRival( sp ) ];
			    	Posicion posicionRemate = new Posicion( 0, Constantes.LARGO_CAMPO_JUEGO / 2 );
			    	if( d < 15 && rivalesAdelante > 0 ){
				    	if( arquero.getX() <= 0 )
				    		posicionRemate = new Posicion( Constantes.LARGO_ARCO/3, Constantes.LARGO_CAMPO_JUEGO / 2 );
				    	else
				    		posicionRemate = new Posicion( -Constantes.LARGO_ARCO/3, Constantes.LARGO_CAMPO_JUEGO / 2 );
			    	}
			    	// Si est� "s�lo" frente al arquero...
			    	if( rivalesAdelante == 1 && d > 13 /*&& Math.abs( jugadorPosicion.getX() ) < Constantes.LARGO_AREA_CHICA/2*/ ){
			    		//jugador.setComando( new ComandoGANA( CORRER_CON_BALON, 90.0, 0.3, false ) );
						Posicion posAvance = new Posicion( jugadorPosicion.getX(), jugadorPosicion.getY()+3 );
						jugador.setComando( new ComandoGANA( GOLPEAR_BALON, posAvance, 0.3, 10.0 ) );
			    		jugador.addComandoSiguiente( new ComandoGANA( GOLPEAR_BALON, GOLPEAR_BALON, posicionRemate, fuerza, 10.0 ) );
					}
			    	else {
				    	jugador.setComando( new ComandoGANA( GOLPEAR_BALON, posicionRemate, fuerza, angulo ) );
			    	}
    				// Mueve a los delanteros para esperar el "rechazo"
					int delanteros = 0;
    		    	for ( int j = 9; j < 11; j++ ){
    		    		if( j!=indiceJugador ){
    		    			Posicion posicion = null;
    		    			if( delanteros%2 == 0 )
    		    				posicion = new Posicion( -Constantes.LARGO_ARCO/2, Constantes.LARGO_CAMPO_JUEGO / 2 - 25 );
    		    			else
    		    				posicion = new Posicion( Constantes.LARGO_ARCO/2, Constantes.LARGO_CAMPO_JUEGO / 2 - 25 );
    		    			jugadores[j].setComando( new ComandoGANA( MOVER_A_POSICION, posicion ) );
    		    			delanteros++;
    		    		}
    		    	}
    			}
				// Si el jugador se est� acercando a la linea final
				else if( jugadorPosicion.getY() > Constantes.LARGO_CAMPO_JUEGO / 2 - Constantes.ANCHO_AREA_GRANDE ){
					Posicion posicionPase = new Posicion( Constantes.LARGO_ARCO / 2, Constantes.LARGO_CAMPO_JUEGO / 2 - 15 );
					if( jugadorPosicion.getX() > 0 )
						posicionPase = new Posicion( -Constantes.LARGO_ARCO / 2, posicionPase.getY() );
					indiceJugadorRecibe = getJugadorMasCercano( sp, posicionPase, indiceJugador, sp.misJugadores() );
    	    		pasarBalon( indiceJugador, indiceJugadorRecibe, sp, posicionPase );
				}
				else {
					// Verifica si est� siendo marcado por delante
					boolean hayRivalesMarcando = false;
					for( int i=0; i<masCercanosRivalesBalon.length && !hayRivalesMarcando; i++ ){
						double dist = sp.rivales()[ masCercanosRivalesBalon[i] ].distancia( sp.balon() );
						if( dist > 15 )
							i = masCercanosRivales.length;
						else {
							if( sp.rivales()[masCercanosRivalesBalon[i]].getY() >= jugadorPosicion.getY()-0.5 )
								hayRivalesMarcando = true;
						}
					}
					if( hayRivalesMarcando ){
		    			if( indiceJugadorRecibe == -1 ){
		    				if( jugadorPosicion.getY() < 0 ){
			    	    		Posicion posicionPase = new Posicion(0,jugadorPosicion.getY()+60);
			    	    		indiceJugadorRecibe = getJugadorMasCercano( sp, posicionPase, indiceJugador, sp.misJugadores() );
			    	    		pasarBalon( indiceJugador, indiceJugadorRecibe, sp, posicionPase );
		    				}
		    				else { // Dribling
			                	double pj = Math.abs( jugadorPosicion.getX() );
			                	double x = Math.random()*16.0-8.0;
			                	if( x < 0 && Constantes.ANCHO_CAMPO/2 - pj < 15 )
			                		x += 10;
			                	if( x > 0 && Constantes.ANCHO_CAMPO/2 - pj < 15 )
			                		x -= 10;
								Posicion posAvance = new Posicion( jugadorPosicion.getX()+x, jugadorPosicion.getY()+3 );
								jugador.setComando( new ComandoGANA( GOLPEAR_BALON, posAvance, 0.5, 10.0 ) );
		    				}
		    			}
		    			else {
		    				pasarBalon( indiceJugador, indiceJugadorRecibe, sp, null );
		    			}
					}
					else {
						//Corre con el bal�n
	                	double pj = Math.abs( jugadorPosicion.getX() );
	                	double x = Math.random()*10.0-5.0;
	                	if( x < 0 && Constantes.ANCHO_CAMPO/2 - pj < 8 )
	                		x += 5;
	                	if( x > 0 && Constantes.ANCHO_CAMPO/2 - pj < 8 )
	                		x -= 5;
						Posicion posAvance = new Posicion( jugadorPosicion.getX()+x, jugadorPosicion.getY()+4 );
						jugador.setComando( new ComandoGANA( GOLPEAR_BALON, posAvance, 0.35, 10.0 ) );
					}
	    		}
    		}
    	}
    	else {
	    	// Voy a sacar si soy el jugador mas cercano al bal�n diferente al portero
	    	if( sp.saco() && ( masCercanosAmigosBalon[0] == indiceJugador || ( masCercanosAmigosBalon[0] == 0 && masCercanosAmigosBalon[1] == indiceJugador ) ) ){
	    		jugador.setComando( new ComandoGANA( SEGUIR_BALON ) );
	    	}
	    	else {
	    		// Valida si nos est�n atacando
    			/*
	    		if( posicionTiroRival != null && Math.abs(posicionTiroRival.getX()) <= Constantes.ANCHO_CAMPO_JUEGO/2 && Math.abs(posicionTiroRival.getY()) <= Constantes.LARGO_CAMPO_JUEGO/2 ) {
		    		int jugadorMasCercano = getJugadorMasCercano( sp, posicionTiroRival, 0, sp.misJugadores() );
		    		if( jugadorMasCercano == indiceJugador ){
		    			jugador.setComando( new ComandoGANA( INTERCEPTAR_PASE, posicionTiroRival ) );
		    			return true;
		    		}
				}
				*/
	    		if( jugadores[indiceJugador].comando == null || jugadores[indiceJugador].comando.comandoTerminado ){
	    			double distAlineacion = sp.balon().distancia( alineacion1[ indiceJugador ] );
		    		if( distAlineacion <= 20 || ( amigoMasCercanoBalon == indiceJugador ) ){
		    			jugador.setComando( new ComandoGANA( SEGUIR_BALON ) );
		    			return true;
		    		}
		    		jugador.setComando( new ComandoGANA( MOVERSE_EN_POSICION ) );
	    		}
	    	}
    	}
    	return false;
    }

    private void pasarBalon( int indiceJugador, int indiceJugadorRecibe, SituacionPartido sp, Posicion posPase ){
    	Posicion jugadorPosicionRecibe = sp.misJugadores()[indiceJugadorRecibe];
    	Posicion jugadorPosicion = sp.misJugadores()[indiceJugador];
    	Posicion posicionPase = posPase;
    	if( posPase == null )
    		posicionPase = new Posicion( jugadorPosicionRecibe.getX(), jugadorPosicionRecibe.getY()+10 );
    	double fuerza = 1.0;
    	double angulo = 45.0;
    	jugadores[indiceJugador].setComando( new ComandoGANA( GOLPEAR_BALON, posicionPase, fuerza, angulo ) );
    	// Si es un mediocampista o un delantero busca la pared
    	if( indiceJugador > 4 && posPase == null && posicionPase.getY()+20 < Constantes.LARGO_CAMPO_JUEGO/2 )
    		jugadores[indiceJugador].addComandoSiguiente( new ComandoGANA( BUSCAR_PARED, new Posicion( jugadorPosicion.getX(), posicionPase.getY()+20 ) ) );
    	jugadores[indiceJugadorRecibe].setComando( new ComandoGANA( RECIBIR_PASE, posicionPase, fuerza, angulo, sp.balon() ) );
    }

    private int buscarMejorPase( int indiceJugador, Posicion jugadorPosicion, SituacionPartido sp, int[] masCercanosAmigos ){
    	int i = 0, indiceJugadorPase = -1, cont = 0;
    	int[] posiblesPases = new int[11];
    	while( i < masCercanosAmigos.length ){
    		if( masCercanosAmigos[i] != indiceJugador ){
    			Posicion recibe = sp.misJugadores()[ masCercanosAmigos[i] ];
    			if( recibe.getY() > jugadorPosicion.getY() && recibe.getY() < Constantes.LARGO_CAMPO_JUEGO/2 && ( recibe.getY() < Constantes.LARGO_CAMPO_JUEGO/2-8 || Math.abs(recibe.getX()) < Constantes.LARGO_AREA_CHICA/2 ) ){
    				double dist = recibe.distancia( jugadorPosicion );
    				if( dist <= 60 ){
    					indiceJugadorPase = masCercanosAmigos[i];
    					posiblesPases[cont] = indiceJugadorPase;
    					cont++;
    				}
    				else
    					i = masCercanosAmigos.length;
    			}
    		}
    		i++;
    	}
    	double maxX = 0;
    	indiceJugadorPase = -1;
    	for( i=0; i<cont; i++ ){
    		double dist = Math.abs( jugadorPosicion.getX() - sp.misJugadores()[ posiblesPases[i] ].getX() );
    		if( dist > maxX ){
    			maxX = dist;
    			indiceJugadorPase = posiblesPases[i];
    		}
    	}
    	return indiceJugadorPase;
    }

    private int buscarPorteroRival( SituacionPartido sp ){
    	int i;
    	JugadorDetalle[] detalleRivales = sp.detalleJugadoresRivales();
    	for( i=0; i<11; i++ ){
    		if( detalleRivales[i].esPortero() )
    			return i;
    	}
    	return 0;
    }

    private int obtenerRivalesAdelante( SituacionPartido sp, Posicion jugadorPosicion ){
	    int rivalesAdelante = 0;
		for( int i=0; i<11; i++ ){
			if( sp.rivales()[i].getY() >= jugadorPosicion.getY() )
				rivalesAdelante++;
		}
		return rivalesAdelante;
    }

    private int getJugadorMasCercano( SituacionPartido sp, Posicion posicion, int indiceJugador, Posicion[] jugadores ){
    	int[] cercanos = posicion.indicesMasCercanos( jugadores );
    	if( cercanos[0] != 0 && cercanos[0] != indiceJugador )
    		return cercanos[0];
    	if( cercanos[1] != 0 && cercanos[1] != indiceJugador )
    		return cercanos[1];
    	return cercanos[2];
    }

    /*private int[] getDefensasMasCercanos( SituacionPartido sp, Posicion posicion, Posicion[] jugadores ){
    	int i, cont = 0;
    	int[] cercanos = posicion.indicesMasCercanos( jugadores ), defensas = new int[11];
    	for( i=0; i<cercanos.length; i++ ){
    		if( jugadores[ cercanos[i] ].getY() < posicion.getY() ){
    			defensas[cont] = cercanos[i];
    			cont++;
    		}
    	}
    	int[] retorno = new int[cont];
    	for( i=0; i<cont; i++ ){
    		retorno[i] = defensas[i];
    	}
    	return retorno;
    }*/

    private double redondeaMultiplo(double valor, double divisor) {
        return Math.round(valor / divisor) * divisor;
    }

    private Posicion castPosicion( Object objeto, Posicion defaultPosicion ){
    	if( objeto == null || !(objeto instanceof Posicion) ){
    		if( defaultPosicion == null )
    			return new Posicion( 0, 0 );
    		return defaultPosicion;
    	}
    	return (Posicion) objeto;
    }

    private double castDouble( Object objeto, double defaultValue ){
    	Double fuerzaObj = (Double)objeto;
		double fuerza = defaultValue;
		if( fuerzaObj != null )
			fuerza = fuerzaObj.doubleValue();
		return fuerza;
    }

	public void getInfoComando(SituacionPartido sp, JugadorGANA jugador, int comando, Object... parametros ){
		//if( jugador.comandoAnterior == null || jugador.comando.comando != jugador.comandoAnterior.comando || jugador.comando.parametroComando1 != jugador.comandoAnterior.parametroComando1 ){
			StringBuffer sb = new StringBuffer("");
			switch( comando ){
				default: sb.append("DEFAULT"); break;
				case RECIBIR_PASE: sb.append("RECIBIR_PASE"); break;
				case BUSCAR_PASE: sb.append("BUSCAR_PASE"); break;
				case BUSCAR_PARED: sb.append("BUSCAR_PARED"); break;
				case INTERCEPTAR_PASE: sb.append("INTERCEPTAR_PASE"); break;
				case MOVER_A_POSICION: sb.append("MOVER_A_POSICION"); break;
				case MOVERSE_EN_POSICION: sb.append("MOVERSE_EN_POSICION"); break;
				case SEGUIR_BALON: sb.append("SEGUIR_BALON"); break;
				case SEGUIR_JUGADOR: sb.append("SEGUIR_JUGADOR"); break;
				case TAPAR: sb.append("TAPAR"); break;
				case ACHICAR: sb.append("ACHICAR"); break;
				case GOLPEAR_BALON: sb.append("GOLPEAR_BALON"); break;
			}
			Object parametroComando1 = ( parametros.length > 0 ) ? parametros[0] : null;
			Object parametroComando2 = ( parametros.length > 1 ) ? parametros[1] : null;
			Object parametroComando3 = ( parametros.length > 2 ) ? parametros[2] : null;
			Object parametroComando4 = ( parametros.length > 3 ) ? parametros[3] : null;
			getInfoParametro( sb, 1, parametroComando1 );
			getInfoParametro( sb, 2, parametroComando2 );
			getInfoParametro( sb, 3, parametroComando3 );
			getInfoParametro( sb, 4, parametroComando4 );
		//}
	}

	private void getInfoParametro( StringBuffer sb, int index, Object parametroComando ){
		sb.append( " p" ).append(index).append(":");
		if( parametroComando == null )
			sb.append( "null" );
		else {
			if( parametroComando instanceof Posicion ){
				sb.append( "(" ).append(((Posicion)parametroComando).getX()).append( "," ).append(((Posicion)parametroComando).getY()).append( ")" );
			}
			else if( parametroComando instanceof Double ){
				sb.append(((Double)parametroComando).doubleValue());
			}
		}
	}

}